#ifndef BASICS_LIBRARY_INCLUDED
#define BASICS_LIBRARY_INCLUDED

#include <utility>

namespace cppt {
    // Same as `template<class T>`
    template<typename T>
    const T &max(const T &a, const T &b) {
        return a > b ? a : b;
    }

    // C++11 `typename std::common_type<T1, T2>::type`, C++14 `std::common_type_t<T1, T2>`
    template<typename T1, typename T2>
    std::common_type_t<T1, T2> max2(T1 a, T2 b) {
        return a > b ? a : b;
    }

    // T might only be part of the type.
    // Optimized version `swap` with `std::move()`.
    template<typename T>
    void swap(T &a, T &b) {
        T tmp = std::move(b);
        b = std::move(a);
        a = std::move(tmp);
    }

    // Deducing the Return Type from the return statements in the function body, `auto` in the template.
    // Same as `template<typename T> auto ismax(const T &a, const T &b) -> decltype(a > b) { ... }`
    template<typename T>
    auto ismax(const T &a, const T &b) {
        return a > b;
    }

    // Another Decucing way, T1 or T2 might happen be a reference type.
    // C++14 `... -> std::decay_t<decltype(a > b)> { return a > b; }`
    template<typename T1, typename T2>
    auto ismax2(T1 a, T2 b) -> typename std::decay<decltype(a > b)>::type {
        return a > b;
    }


}
#endif